//
// Created by goldfish on 24/3/25.
//



#ifndef TTY_LOGIN_DATABASEMANAGER_H
#define TTY_LOGIN_DATABASEMANAGER_H
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

#include "databaseManager.h"
#include "sqlite3.h"
using namespace std;
class DatabaseManager {
    sqlite3* db{};
    std::string db_path;

public:

    DatabaseManager(const string& db_path,const string& db_name) ;
    ~DatabaseManager() {
        sqlite3_close(db);
    }

    void create_table();

    int update_login_count(const string& tty_name) {
        const char* sql =
                "INSERT INTO tty_login (tty_name, tty_login_times) VALUES (?, 1)"
                "ON CONFLICT(tty_name) DO UPDATE SET tty_login_times = tty_login_times + 1;";

        auto stmt = prepare_statement(sql);
        sqlite3_bind_text(stmt.get(), 1, tty_name.c_str(), -1, SQLITE_STATIC);
        execute_statement(stmt);

        return get_login_count(tty_name);
    }

private:
    int get_login_count(const string& tty_name) {
        const char* sql = "SELECT tty_login_times FROM tty_login WHERE tty_name = ?;";
        auto stmt = prepare_statement(sql);
        sqlite3_bind_text(stmt.get(), 1, tty_name.c_str(), -1, SQLITE_STATIC);

        if(sqlite3_step(stmt.get()) == SQLITE_ROW) {
            return sqlite3_column_int(stmt.get(), 0);
        }
        return 0;
    }

    unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)> prepare_statement(const char* sql) {
        sqlite3_stmt* stmt;
        if(sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
            throw runtime_error("Prepare failed: " + string(sqlite3_errmsg(db)));
        }
        return {stmt, sqlite3_finalize};
    }

    void execute_sql(const char* sql) {
        char* err_msg;
        if(sqlite3_exec(db, sql, nullptr, nullptr, &err_msg) != SQLITE_OK) {
            string error = "SQL error: " + string(err_msg);
            sqlite3_free(err_msg);
            throw runtime_error(error);
        }
    }

    void execute_statement(unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)>& stmt) {
        if(sqlite3_step(stmt.get()) != SQLITE_DONE) {
            throw runtime_error("Execution failed: " + string(sqlite3_errmsg(db)));
        }
    }
};



#endif //TTY_LOGIN_DATABASEMANAGER_H
